package com.huatai.common.tool;

/**
 * @program: ht-system
 * @description: beanmap
 * @author: songxiude
 * @create: 2023-01-31 15:28
 **/

import java.security.ProtectionDomain;
import org.springframework.asm.ClassVisitor;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.cglib.core.AbstractClassGenerator;
import org.springframework.cglib.core.ReflectUtils;

public abstract class HtBeanMap extends BeanMap {
    protected HtBeanMap() {
    }

    protected HtBeanMap(Object bean) {
        super(bean);
    }

    public static HtBeanMap create(Object bean) {
        HtGenerator gen = new HtGenerator();
        gen.setBean(bean);
        return gen.create();
    }

    public abstract HtBeanMap newInstance(Object o);

    public static class HtGenerator extends AbstractClassGenerator {
        private static final AbstractClassGenerator.Source SOURCE = new AbstractClassGenerator.Source(HtBeanMap.class.getName());
        private Object bean;
        private Class beanClass;
        private int require;

        public HtGenerator() {
            super(SOURCE);
        }

        public void setBean(Object bean) {
            this.bean = bean;
            if (bean != null) {
                this.beanClass = bean.getClass();
            }

        }

        public void setBeanClass(Class beanClass) {
            this.beanClass = beanClass;
        }

        public void setRequire(int require) {
            this.require = require;
        }

        protected ClassLoader getDefaultClassLoader() {
            return this.beanClass.getClassLoader();
        }

        protected ProtectionDomain getProtectionDomain() {
            return ReflectUtils.getProtectionDomain(this.beanClass);
        }

        public HtBeanMap create() {
            if (this.beanClass == null) {
                throw new IllegalArgumentException("Class of bean unknown");
            } else {
                this.setNamePrefix(this.beanClass.getName());
                HtBeanMapKey key = new HtBeanMapKey(this.beanClass, this.require);
                return (HtBeanMap)super.create(key);
            }
        }

        public void generateClass(ClassVisitor v) throws Exception {
            new BladeBeanMapEmitter(v, this.getClassName(), this.beanClass, this.require);
        }

        protected Object firstInstance(Class type) {
            return ((BeanMap)ReflectUtils.newInstance(type)).newInstance(this.bean);
        }

        protected Object nextInstance(Object instance) {
            return ((BeanMap)instance).newInstance(this.bean);
        }
    }
}

